package us.mooresr.aircraftscheduling.client.ui;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import us.mooresr.aircraftscheduling.client.events.ReservationChangedEvent;
import us.mooresr.aircraftscheduling.client.events.ReservationChangedEvent.ReservationChangedHandler;
import us.mooresr.aircraftscheduling.client.events.ReservationCreatedEvent;
import us.mooresr.aircraftscheduling.client.events.ReservationCreatedEvent.ReservationCreatedHandler;
import us.mooresr.aircraftscheduling.client.events.ReservationDeletedEvent;
import us.mooresr.aircraftscheduling.client.events.ReservationDeletedEvent.ReservationDeletedHandler;
import us.mooresr.aircraftscheduling.shared.model.Reservation;
import us.mooresr.aircraftscheduling.shared.model.User;

import com.gwtplatform.mvp.client.ViewImpl;
import com.gwtplatform.mvp.client.ViewWithUiHandlers;
import com.google.gwt.cell.client.ButtonCell;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.inject.Inject;

public class ReservationListView extends ViewWithUiHandlers<ReservationListUiHandlers> 
	implements ReservationListPresenter.MyView {

	private final HTMLPanel widget;
	private Boolean showPast = true;

	public interface Binder extends UiBinder<HTMLPanel, ReservationListView> {
	}
	
	@UiField
	CheckBox showPastControl;
	
	@UiField(provided = true)
	DataGrid<Reservation> cellTable;

	private ListDataProvider<Reservation> dataProvider = new ListDataProvider<Reservation>();
	
	private static Comparator<Reservation> comparator = new Comparator<Reservation>() {

		@Override
		public int compare(Reservation arg0, Reservation arg1) {
			return arg0.getStart().compareTo(arg1.getStart());
		}
		
	};
	
	interface DataGridResource extends DataGrid.Resources {
		@Source (value={DataGrid.Style.DEFAULT_CSS, "../resources/styling/DataGridStyle.css"})
		DataGrid.Style dataGridStyle();
	}
	
	@Inject
	public ReservationListView(final Binder binder, final EventBus eventBus) {

		DataGridResource resource = GWT.create(DataGridResource.class);
		cellTable = new DataGrid<Reservation>(15, resource);
		
		setupTableColumns();
		
		cellTable.setEmptyTableWidget(new HTML("No Reservations"));
		
		dataProvider.addDataDisplay(cellTable);
		
		eventBus.addHandler(ReservationCreatedEvent.getType(), new ReservationCreatedHandler() {

			@SuppressWarnings("deprecation")
			@Override
			public void onReservationCreated(ReservationCreatedEvent event) {
				// A new reservation has been created - add it to the list
				
				if (showPastControl.getValue() == false) {
					Date today = new Date();
					today.setHours(0);
					today.setMinutes(0);
					if (event.getReservation().getEnd().before(today)) {
						// It's in the past, no need to add it
						return;
					}
				}
				
				List<Reservation> list = dataProvider.getList();
				list.add(event.getReservation());
				
				Collections.sort(list, comparator);
				
			}
			
		});
		
		eventBus.addHandler(ReservationChangedEvent.getType(), new ReservationChangedHandler() {

			@Override
			public void onReservationChanged(ReservationChangedEvent event) {
				List<Reservation> list = dataProvider.getList();
				for (Reservation r : list) {
					if (r.getReservationId() == event.getReservation().getReservationId()) {
						list.remove(r);
						
						// If it's in the past and we're not showing past events we don't need to add it
						if (showPastControl.getValue() == false) {
							Date today = new Date();
							today.setHours(0);
							today.setMinutes(0);
							if (event.getReservation().getEnd().before(today)) {
								// It's in the past, no need to add it
								return;
							}
						}
						
						list.add(event.getReservation());
						break;
					}
				}
				
			}
			
		});
		
		eventBus.addHandler(ReservationDeletedEvent.getType(), new ReservationDeletedHandler() {

			@Override
			public void onReservationDeleted(ReservationDeletedEvent event) {
				List<Reservation> list = dataProvider.getList();
				for (Reservation r : list) {
					if (r.getReservationId().equals(event.getReservation().getReservationId())) {
						list.remove(r);
						break;
					}
				}
				
			}
			
		});
		
		widget = binder.createAndBindUi(this);
		
	}

	private void setupTableColumns() {
		
		// Reserved By column
		TextColumn<Reservation> nameColumn = new TextColumn<Reservation>() {
			@Override
			public String getValue(Reservation object) {
				return object.getReservingUserName();
			}			
		};
		cellTable.addColumn(nameColumn, "Reserved By");
			
		// Start Date column
		DateCell startCell = new DateCell(DateTimeFormat.getFormat("EEE, MMM d, h:mm a"));
		Column<Reservation, Date> fromColumn = new Column<Reservation, Date>(startCell) {

			@Override
			public Date getValue(Reservation object) {
				return object.getStart();
			}

			
		};
		cellTable.addColumn(fromColumn, "Start");
		
		// End Date column
		DateCell endCell = new DateCell(DateTimeFormat.getFormat("EEE, MMM d, h:mm a"));
		Column<Reservation, Date> endColumn = new Column<Reservation, Date>(endCell) {

			@Override
			public Date getValue(Reservation object) {
				return object.getEnd();
			}


		};
		cellTable.addColumn(endColumn, "End");
		
		// Notes column
		TextColumn<Reservation> notesColumn = new TextColumn<Reservation>() {

			@Override
			public String getValue(Reservation object) {
				return object.getNotes();
			}
		
		};
		cellTable.addColumn(notesColumn, "Notes");
		
		// Edit column
		ButtonCell editCell = new ButtonCell();
		Column<Reservation, String> editColumn = new Column<Reservation, String>(editCell) {

			@Override
			public String getValue(Reservation object) {
				return "Edit";
			}
			
		};
		editColumn.setFieldUpdater(new FieldUpdater<Reservation, String>() {
			@Override
			public void update(int index, Reservation object, String value) {
				getUiHandlers().editReservation(object);		
			}
			
		});
		String actionsHeader = new String("Actions");
		cellTable.addColumn(editColumn, actionsHeader);
		
		// Delete column
		ButtonCell deleteCell = new ButtonCell();
		Column<Reservation, String> deleteColumn = new Column<Reservation, String>(deleteCell) {

			@Override
			public String getValue(Reservation object) {
				return "Delete";
			}
			
		};
		deleteColumn.setFieldUpdater(new FieldUpdater<Reservation, String>() {

			@Override
			public void update(int index, Reservation object, String value) {
				if (Window.confirm("Are you sure you want to delete this reservation?")) {
					getUiHandlers().deleteReservation(object);
				}
				
			}
			
		});
		cellTable.addColumn(deleteColumn, actionsHeader);
		
	}

	@Override
	public Widget asWidget() {
		return widget;
	}
	
	
	@UiHandler("createButton")
	void onCreateClicked(ClickEvent event) {
		getUiHandlers().createReservation();
		
	}
	
	@UiHandler("showPastControl")
	void onShowPastClicked(ClickEvent event) {
		getUiHandlers().refreshList(showPastControl.getValue());
	}

	@Override
	public void setData(ArrayList<Reservation> reservationList) {
		List<Reservation> list = dataProvider.getList();
		
		list.clear();
		
		for (Reservation r : reservationList) {
			list.add(r);
		}
		
		
		render();
		
	}

	private void render() {
		// TODO Re-render the table.  Do we need to do anything here?
		
	}
	

}
